home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Resources / Online / Term / Extras / Source / term-source.lha / Transfer.c < prev    next >
C/C++ Source or Header  |  1996-10-20  |  46KB  |  2,206 lines

  1. /*
  2. **    Transfer.c
  3. **
  4. **    File transfer routines
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16.     /* Prototypes for local routines. */
  17.  
  18. STATIC VOID CommonStartReceive(LONG Type, STRPTR Name, BOOL WaitForIt);
  19. STATIC BOOL CommonStartSend(LONG Type, STRPTR TheFile, struct FileTransferInfo **TransferInfoPtr, BOOL WaitForIt);
  20. STATIC BOOL SelectProtocol(struct Window *ParentWindow);
  21. STATIC BOOL StartSend(BOOL IsBinary);
  22. STATIC BOOL StartReceive(BOOL IsBinary);
  23. STATIC VOID StripLibrary(STRPTR Protocol, STRPTR NameBuffer, LONG NameSize);
  24. STATIC BOOL IsZModem(STRPTR String);
  25. STATIC VOID CommonExternalSetup(STRPTR Buffer);
  26. STATIC BOOL CommonXPRSetup(STRPTR ProtocolName, BOOL IgnoreOptions);
  27. STATIC struct Node *CreateArgName(STRPTR String);
  28. STATIC STRPTR BuildString(STRPTR Source, STRPTR From, STRPTR To, BYTE Type, BOOL ReceiveMode, STRPTR SingleFile, struct FileTransferInfo *Info, LONG *Error);
  29. STATIC STRPTR ReplaceName(STRPTR Source);
  30. STATIC VOID CommonStartSendXPR(LONG Type, BOOL IsBinary, BOOL WaitForIt);
  31. STATIC VOID CommonSendXPRCleanup(BOOL WaitForIt);
  32. STATIC VOID CommonStartReceiveXPR(LONG Type, BOOL IsBinary, BOOL WaitForIt);
  33. STATIC LONG TransferCompare(struct FileTransferNode **A, struct FileTransferNode **B);
  34.  
  35.     /* CommonStartReceive():
  36.      *
  37.      *    Receive files via XPR or a different protocol.
  38.      */
  39.  
  40. STATIC VOID
  41. CommonStartReceive(LONG Type,STRPTR Name,BOOL WaitForIt)
  42. {
  43.     STRPTR From,To,Cmd;
  44.     BOOL IsBinary;
  45.     LONG Mode;
  46.  
  47.     if(Type == TRANSFER_ASCII && Config->TransferConfig->ASCIIDownloadType == XFER_INTERNAL)
  48.     {
  49.         InternalASCIIDownload(Name,WaitForIt);
  50.  
  51.         return;
  52.     }
  53.  
  54.     IsBinary = FALSE;
  55.  
  56.     switch(Type)
  57.     {
  58.         case TRANSFER_BINARY:
  59.  
  60.             Cmd        = Config->TransferConfig->BinaryDownloadLibrary;
  61.             Mode    = Config->TransferConfig->BinaryDownloadType;
  62.             From    = Config->PathConfig->BinaryUploadPath;
  63.             To        = Config->PathConfig->BinaryDownloadPath;
  64.  
  65.             IsBinary = TRUE;
  66.             break;
  67.  
  68.         case TRANSFER_TEXT:
  69.  
  70.             Cmd        = Config->TransferConfig->TextDownloadLibrary;
  71.             Mode    = Config->TransferConfig->TextDownloadType;
  72.             From    = Config->PathConfig->TextUploadPath;
  73.             To        = Config->PathConfig->TextDownloadPath;
  74.             break;
  75.  
  76.         case TRANSFER_ASCII:
  77.  
  78.             Cmd        = Config->TransferConfig->ASCIIDownloadLibrary;
  79.             Mode    = Config->TransferConfig->ASCIIDownloadType;
  80.             From    = Config->PathConfig->ASCIIUploadPath;
  81.             To        = Config->PathConfig->ASCIIDownloadPath;
  82.             break;
  83.     }
  84.  
  85.     if(Mode == XFER_DEFAULT && Config->TransferConfig->DefaultType == XFER_EXTERNALPROGRAM)
  86.     {
  87.         Cmd        = Config->TransferConfig->DefaultLibrary;
  88.         Mode    = XFER_EXTERNALPROGRAM;
  89.     }
  90.  
  91.     if(Mode == XFER_EXTERNALPROGRAM)
  92.     {
  93.         STRPTR    String;
  94.         LONG    Error;
  95.  
  96.         BlockWindows();
  97.  
  98.         if(String = BuildString(Cmd,From,To,Type,TRUE,Name,NULL,&Error))
  99.         {
  100.             ClearSerial();
  101.  
  102.             LaunchCommand(String);
  103.  
  104.             RestartSerial();
  105.  
  106.             FreeVecPooled(String);
  107.         }
  108.  
  109.         ReleaseWindows();
  110.     }
  111.     else
  112.     {
  113.         struct FileRequester    *FileRequest;
  114.         UBYTE                     DummyBuffer[MAX_FILENAME_LENGTH];
  115.         BPTR                     NewDir = NULL,
  116.                                  OldDir = NULL;
  117.  
  118.         ClearGenericList(GenericListTable[GLIST_DOWNLOAD],FALSE);
  119.  
  120.             /* Select the download path. */
  121.  
  122.         switch(Type)
  123.         {
  124.             case TRANSFER_BINARY:
  125.  
  126.                 DownloadPath = Config->PathConfig->BinaryDownloadPath;
  127.                 break;
  128.  
  129.             case TRANSFER_TEXT:
  130.  
  131.                 DownloadPath = Config->PathConfig->TextDownloadPath;
  132.                 break;
  133.  
  134.             case TRANSFER_ASCII:
  135.  
  136.                 DownloadPath = Config->PathConfig->ASCIIDownloadPath;
  137.                 break;
  138.         }
  139.  
  140.         if(DownloadPath[0])
  141.         {
  142.             if(NewDir = Lock(DownloadPath,ACCESS_READ))
  143.                 OldDir = CurrentDir(NewDir);
  144.         }
  145.  
  146.         BlockWindows();
  147.  
  148.             /* Set up the library if necessary. */
  149.  
  150.         if(!XProtocolBase)
  151.         {
  152.             if(SelectProtocol(Window))
  153.             {
  154.                 if(ProtocolSetup(FALSE))
  155.                     SaveProtocolOpts();
  156.             }
  157.         }
  158.  
  159.         if(XProtocolBase)
  160.         {
  161.             SetTransferMenu(TRUE);
  162.  
  163.                 /* Do we need to ask the user for
  164.                  * the destination file name?
  165.                  */
  166.  
  167.             if(TransferBits & XPRS_NORECREQ)
  168.                 CommonStartReceiveXPR(Type,IsBinary,WaitForIt);
  169.             else
  170.             {
  171.                 if(!Name)
  172.                 {
  173.                     LimitedStrcpy(sizeof(DummyBuffer),DummyBuffer,DownloadPath);
  174.  
  175.                     if(FileRequest = SaveFile(Window,LocaleString(MSG_TERMTRANSFER_DOWNLOAD_FILE_TXT + (Type - TRANSFER_BINARY)),LocaleString(MSG_TERMTRANSFER_RECEIVE_TXT),NULL,DummyBuffer,sizeof(DummyBuffer)))
  176.                     {
  177.                         FreeAslRequest(FileRequest);
  178.  
  179.                             /* Save the download path. */
  180.  
  181.                         strcpy(DownloadPath,DummyBuffer);
  182.                         *PathPart(DownloadPath) = 0;
  183.  
  184.                         ConfigChanged = TRUE;
  185.  
  186.                             /* Install the name of the file to receive. */
  187.  
  188.                         XprIO->xpr_filename = DummyBuffer;
  189.  
  190.                         Name = DummyBuffer;
  191.                     }
  192.                 }
  193.                 else
  194.                 {
  195.                     STRPTR Index;
  196.  
  197.                     strcpy(DownloadPath,Name);
  198.  
  199.                     ConfigChanged = TRUE;
  200.  
  201.                     Index = PathPart(DownloadPath);
  202.  
  203.                     *Index = 0;
  204.  
  205.                     XprIO->xpr_filename = Name;
  206.                 }
  207.  
  208.                     /* Download the file(s). */
  209.  
  210.                 if(Name)
  211.                     CommonStartReceiveXPR(Type,IsBinary,WaitForIt);
  212.             }
  213.         }
  214.         else
  215.             SetTransferMenu(TRUE);
  216.  
  217.         if(NewDir)
  218.             UnLock(CurrentDir(OldDir));
  219.  
  220.         if(SendAbort)
  221.         {
  222.             CancelZModem();
  223.             SendAbort = FALSE;
  224.         }
  225.  
  226.         ReleaseWindows();
  227.  
  228.         DownloadPath = NULL;
  229.  
  230.         DidTransfer = FALSE;
  231.  
  232.         if(WaitForIt)
  233.         {
  234.             if(Config->CommandConfig->DownloadMacro[0])
  235.                 SerialCommand(Config->CommandConfig->DownloadMacro);
  236.         }
  237.     }
  238. }
  239.  
  240.     /* CommonStartSend():
  241.      *
  242.      *    Send files via XPR or a different protocol.
  243.      */
  244.  
  245. STATIC BOOL
  246. CommonStartSend(LONG Type,STRPTR TheFile,struct FileTransferInfo **TransferInfoPtr,BOOL WaitForIt)
  247. {
  248.     STRPTR From,To,Name;
  249.     BOOL IsBinary;
  250.     LONG Mode;
  251.  
  252.     if(TheFile)
  253.         TheFile = ReplaceName(TheFile);
  254.  
  255.     if(Type == TRANSFER_ASCII && Config->TransferConfig->ASCIIDownloadType == XFER_INTERNAL)
  256.         return(InternalASCIIUpload(TheFile,WaitForIt));
  257.  
  258.     IsBinary = FALSE;
  259.  
  260.     switch(Type)
  261.     {
  262.         case TRANSFER_BINARY:
  263.  
  264.             Name    = Config->TransferConfig->BinaryUploadLibrary;
  265.             Mode    = Config->TransferConfig->BinaryUploadType;
  266.             From    = Config->PathConfig->BinaryUploadPath;
  267.             To        = Config->PathConfig->BinaryDownloadPath;
  268.  
  269.             IsBinary = TRUE;
  270.             break;
  271.  
  272.         case TRANSFER_TEXT:
  273.  
  274.             Name    = Config->TransferConfig->TextUploadLibrary;
  275.             Mode    = Config->TransferConfig->TextUploadType;
  276.             From    = Config->PathConfig->TextUploadPath;
  277.             To        = Config->PathConfig->TextDownloadPath;
  278.             break;
  279.  
  280.         case TRANSFER_ASCII:
  281.  
  282.             Name    = Config->TransferConfig->ASCIIUploadLibrary;
  283.             Mode    = Config->TransferConfig->ASCIIUploadType;
  284.             From    = Config->PathConfig->ASCIIUploadPath;
  285.             To        = Config->PathConfig->ASCIIDownloadPath;
  286.             break;
  287.     }
  288.  
  289.     if(Mode == XFER_DEFAULT && Config->TransferConfig->DefaultType == XFER_EXTERNALPROGRAM)
  290.     {
  291.         Name    = Config->TransferConfig->DefaultLibrary;
  292.         Mode    = XFER_EXTERNALPROGRAM;
  293.     }
  294.  
  295.     if(Mode == XFER_EXTERNALPROGRAM)
  296.     {
  297.         STRPTR    String;
  298.         LONG    Error;
  299.         BOOL    Result;
  300.  
  301.         BlockWindows();
  302.  
  303.         if(String = BuildString(Name,From,To,Type,FALSE,TheFile,TransferInfoPtr ? *TransferInfoPtr : NULL,&Error))
  304.         {
  305.             ClearSerial();
  306.  
  307.             Result = LaunchCommand(String);
  308.  
  309.             RestartSerial();
  310.  
  311.             if(TransferInfoPtr)
  312.             {
  313.                 FreeFileTransferInfo(*TransferInfoPtr);
  314.  
  315.                 *TransferInfoPtr = NULL;
  316.             }
  317.  
  318.             FreeVecPooled(String);
  319.         }
  320.         else
  321.             Result = FALSE;
  322.  
  323.         ReleaseWindows();
  324.  
  325.         return(Result);
  326.     }
  327.     else
  328.     {
  329.         struct FileRequester    *FileRequest;
  330.         UBYTE                     DummyBuffer[MAX_FILENAME_LENGTH];
  331.         STRPTR                     UploadPath;
  332.         BOOL                     DidSend = TRUE;
  333.         BPTR                     NewDir = NULL,
  334.                                  OldDir = NULL;
  335.  
  336.             /* We are uploading data. */
  337.  
  338.         Uploading = TRUE;
  339.  
  340.             /* Select the upload path. */
  341.  
  342.         switch(Type)
  343.         {
  344.             case TRANSFER_BINARY:
  345.  
  346.                 UploadPath = Config->PathConfig->BinaryUploadPath;
  347.                 break;
  348.  
  349.             case TRANSFER_TEXT:
  350.  
  351.                 UploadPath = Config->PathConfig->TextUploadPath;
  352.                 break;
  353.  
  354.             case TRANSFER_ASCII:
  355.  
  356.                 UploadPath = Config->PathConfig->ASCIIUploadPath;
  357.                 break;
  358.         }
  359.  
  360.         if(UploadPath[0])
  361.         {
  362.             if(NewDir = Lock(UploadPath,ACCESS_READ))
  363.                 OldDir = CurrentDir(NewDir);
  364.         }
  365.  
  366.         BlockWindows();
  367.  
  368.             /* If not initialized, try to set up a new
  369.              * external transfer protocol.
  370.              */
  371.  
  372.         if(!XProtocolBase)
  373.         {
  374.             if(SelectProtocol(Window))
  375.             {
  376.                 if(ProtocolSetup(FALSE))
  377.                     SaveProtocolOpts();
  378.             }
  379.         }
  380.  
  381.         if(XProtocolBase)
  382.         {
  383.             SetTransferMenu(TRUE);
  384.  
  385.                 /* Do we need to use our own file requester or
  386.                  * will xpr handle this job for us?
  387.                  */
  388.  
  389.             if((TransferBits & XPRS_NOSNDREQ) || TheFile || TransferInfoPtr)
  390.             {
  391.                 if(TheFile)
  392.                     XprIO->xpr_filename = TheFile;
  393.  
  394.                 if(TransferInfoPtr)
  395.                     XprIO->xpr_filename = (*TransferInfoPtr)->CurrentFile->Name;
  396.  
  397.                 CommonStartSendXPR(Type,IsBinary,WaitForIt);
  398.  
  399.                 if(TransferInfoPtr)
  400.                 {
  401.                     FreeFileTransferInfo(*TransferInfoPtr);
  402.  
  403.                     *TransferInfoPtr = NULL;
  404.                 }
  405.             }
  406.             else
  407.             {
  408.                     /* We will need the file requester to find
  409.                      * out which file(s) are to be transferred.
  410.                      * Multiple files and wildcards are
  411.                      * supported as well as plain file names.
  412.                      */
  413.  
  414.                 DummyBuffer[0] = 0;
  415.  
  416.                 if(FileRequest = OpenSeveralFiles(Window,LocaleString(MSG_TERMTRANSFER_UPLOAD_FILE_TXT + (Type - TRANSFER_BINARY)),LocaleString(MSG_TERMTRANSFER_SEND_TXT),NULL,DummyBuffer,sizeof(DummyBuffer)))
  417.                 {
  418.                     strcpy(UploadPath,FileRequest->fr_Drawer);
  419.  
  420.                     ConfigChanged = TRUE;
  421.  
  422.                     if(FileTransferInfo = BuildFileTransferInfo(FileRequest))
  423.                     {
  424.                             /* Make sure that at least the
  425.                              * first file gets transferred
  426.                              * in case the protocol does
  427.                              * no support batch upload.
  428.                              */
  429.  
  430.                         XprIO->xpr_filename = ReplaceName(FileTransferInfo->CurrentFile->Name);
  431.  
  432.                         CommonStartSendXPR(Type,IsBinary,WaitForIt);
  433.  
  434.                         if(FileTransferInfo)
  435.                         {
  436.                             FreeFileTransferInfo(FileTransferInfo);
  437.  
  438.                             FileTransferInfo = NULL;
  439.                         }
  440.                     }
  441.  
  442.                     FreeAslRequest(FileRequest);
  443.                 }
  444.                 else
  445.                     DidSend = FALSE;
  446.             }
  447.         }
  448.         else
  449.             SetTransferMenu(TRUE);
  450.  
  451.         if(NewDir)
  452.             UnLock(CurrentDir(OldDir));
  453.  
  454.         CommonSendXPRCleanup(WaitForIt);
  455.  
  456.         return(DidSend);
  457.     }
  458. }
  459.  
  460.     /* SelectProtocol(STRPTR Name,struct Window *ParentWindow):
  461.      *
  462.      *    Select a different transfer protocol library using
  463.      *    the asl.library file requester.
  464.      */
  465.  
  466. STATIC BOOL
  467. SelectProtocol(struct Window *ParentWindow)
  468. {
  469.     UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
  470.  
  471.     strcpy(LocalBuffer,LastXprLibrary);
  472.  
  473.     if(PickFile(ParentWindow,"Libs:","xpr#?.library",LocaleString(MSG_TERMXPR_SELECT_TRANSFER_PROTOCOL_TXT),LocalBuffer,NT_LIBRARY))
  474.     {
  475.         if(Stricmp(LocalBuffer,LastXprLibrary))
  476.         {
  477.             strcpy(LastXprLibrary,LocalBuffer);
  478.  
  479.             return(TRUE);
  480.         }
  481.     }
  482.  
  483.     return(FALSE);
  484. }
  485.  
  486.     /* StartSend(BOOL IsBinary):
  487.      *
  488.      *    Start sending files with the XPR protocol.
  489.      */
  490.  
  491. STATIC BOOL
  492. StartSend(BOOL IsBinary)
  493. {
  494.     if(ReadRequest && WriteRequest)
  495.     {
  496.         BOOL Failed;
  497.  
  498.         BinaryTransfer = IsBinary;
  499.  
  500.         if(XProtocolSend(XprIO))
  501.             Failed = FALSE;
  502.         else
  503.             Failed = TRUE;
  504.  
  505.             /* Always return to binary transfer mode */
  506.  
  507.         BinaryTransfer = TRUE;
  508.  
  509.             /* In case the transfer has been aborted,
  510.              * flush the input buffer of dirty data.
  511.              */
  512.  
  513.         if(TransferAborted)
  514.             CompletelyFlushSerialRead();
  515.  
  516.         return(Failed);
  517.     }
  518.     else
  519.         return(TRUE);
  520. }
  521.  
  522.     /* StartReceive(BOOL IsBinary):
  523.      *
  524.      *    Start receiving files with the XPR protocol.
  525.      */
  526.  
  527. STATIC BOOL
  528. StartReceive(BOOL IsBinary)
  529. {
  530.     if(ReadRequest && WriteRequest)
  531.     {
  532.         BOOL Failed;
  533.  
  534.         BinaryTransfer = IsBinary;
  535.  
  536.         if(XProtocolReceive(XprIO))
  537.             Failed = FALSE;
  538.         else
  539.             Failed = TRUE;
  540.  
  541.             /* Always return to binary transfer mode */
  542.  
  543.         BinaryTransfer = TRUE;
  544.  
  545.         return(Failed);
  546.     }
  547.     else
  548.         return(TRUE);
  549. }
  550.  
  551.     /* StripLibrary(STRPTR Protocol,STRPTR NameBuffer):
  552.      *
  553.      *    Strip the .library part from a file name.
  554.      */
  555.  
  556. STATIC VOID
  557. StripLibrary(STRPTR Protocol,STRPTR NameBuffer,LONG NameSize)
  558. {
  559.     LONG i;
  560.  
  561.     CopyMem(FilePart(Protocol),NameBuffer,NameSize - 1);
  562.     NameBuffer[NameSize - 1] = 0;
  563.  
  564.     for(i = strlen(NameBuffer) - 1 ; i >= 0 ; i--)
  565.     {
  566.         if(NameBuffer[i] == '.')
  567.         {
  568.             NameBuffer[i] = 0;
  569.             break;
  570.         }
  571.     }
  572. }
  573.  
  574.     /* IsZModem(STRPTR String):
  575.      *
  576.      *    Checks if a file name has a "zmodem" string embedded.
  577.      */
  578.  
  579. STATIC BOOL
  580. IsZModem(STRPTR String)
  581. {
  582.     LONG i;
  583.  
  584.     for(i = 0 ; i <= strlen(String) - 6 ; i++)
  585.     {
  586.         if(!Stricmp(&String[i],"zmodem"))
  587.             return(TRUE);
  588.     }
  589.  
  590.     return(FALSE);
  591. }
  592.  
  593.     /* CommonExternalSetup(STRPTR Buffer):
  594.      *
  595.      *    Set up the name of an external file transfer protocol.
  596.      */
  597.  
  598. STATIC VOID
  599. CommonExternalSetup(STRPTR Buffer)
  600. {
  601.     UBYTE NameBuffer[MAX_FILENAME_LENGTH];
  602.     LONG i;
  603.  
  604.     while(*Buffer == ' ')
  605.         Buffer++;
  606.  
  607.     if(!Strnicmp(Buffer,"run",3))
  608.         Buffer += 3;
  609.  
  610.     while(*Buffer == ' ')
  611.         Buffer++;
  612.  
  613.     CopyMem(FilePart(Buffer),NameBuffer,sizeof(NameBuffer) - 1);
  614.     NameBuffer[sizeof(NameBuffer) - 1] = 0;
  615.  
  616.     for(i = 0 ; i < sizeof(NameBuffer) ; i++)
  617.     {
  618.         if(NameBuffer[i] == ' ')
  619.         {
  620.             NameBuffer[i] = 0;
  621.             break;
  622.         }
  623.     }
  624.  
  625.     NameBuffer[0] = ToUpper(NameBuffer[0]);
  626.     strcpy(TransferProtocolName,NameBuffer);
  627.  
  628.     UsesZModem = IsZModem(NameBuffer);
  629.  
  630.     SetTransferMenu(TRUE);
  631. }
  632.  
  633.     /* CommonXPRSetup(STRPTR ProtocolName,BOOL IgnoreOptions):
  634.      *
  635.      *    Set up and initialize an XPR file transfer protocol.
  636.      */
  637.  
  638. STATIC BOOL
  639. CommonXPRSetup(STRPTR ProtocolName,BOOL IgnoreOptions)
  640. {
  641.     UBYTE NameBuffer[MAX_FILENAME_LENGTH];
  642.     BOOL Result;
  643.  
  644.         /* Clear the XPR interface buffer. */
  645.  
  646.     memset(XprIO,0,sizeof(struct XPR_IO));
  647.  
  648.         /* Copy the name of the library. */
  649.  
  650.     StripLibrary(ProtocolName,NameBuffer,sizeof(NameBuffer));
  651.  
  652.         /* Check if the transfer protocol is a sort of ZModem. */
  653.  
  654.     UsesZModem = IsZModem(NameBuffer);
  655.  
  656.         /* Reset the scanner. */
  657.  
  658.     ResetDataFlowFilter();
  659.  
  660.         /* Obtain the protocol default settings. */
  661.  
  662.     if(IgnoreOptions)
  663.         ProtocolOptsBuffer[0] = 0;
  664.     else
  665.         GetEnvDOS(NameBuffer,ProtocolOptsBuffer,sizeof(ProtocolOptsBuffer));
  666.  
  667.     NameBuffer[3] = ToUpper(NameBuffer[3]);
  668.  
  669.         /* Initialize the interface structure. */
  670.  
  671.     XprIO->xpr_filename        = ProtocolOptsBuffer;
  672.     XprIO->xpr_extension    = 4;
  673.  
  674.     #ifdef USE_GLUE
  675.         XprIO->xpr_fopen        = xpr_fopen_glue;
  676.         XprIO->xpr_fclose        = xpr_fclose_glue;
  677.         XprIO->xpr_fread        = xpr_fread_glue;
  678.         XprIO->xpr_fwrite        = xpr_fwrite_glue;
  679.         XprIO->xpr_sread        = xpr_sread_glue;
  680.         XprIO->xpr_swrite        = xpr_swrite_glue;
  681.         XprIO->xpr_sflush        = xpr_sflush;
  682.         XprIO->xpr_update        = xpr_update_glue;
  683.         XprIO->xpr_chkabort        = xpr_chkabort;
  684.         XprIO->xpr_gets            = xpr_gets_glue;
  685.         XprIO->xpr_setserial    = xpr_setserial_glue;
  686.         XprIO->xpr_ffirst        = xpr_ffirst_glue;
  687.         XprIO->xpr_fnext        = xpr_fnext_glue;
  688.         XprIO->xpr_finfo        = xpr_finfo_glue;
  689.         XprIO->xpr_fseek        = xpr_fseek_glue;
  690.         XprIO->xpr_options        = xpr_options_glue;
  691.         XprIO->xpr_unlink        = xpr_unlink_glue;
  692.         XprIO->xpr_squery        = xpr_squery;
  693.         XprIO->xpr_getptr        = xpr_getptr_glue;
  694.     #else
  695.         XprIO->xpr_fopen        = xpr_fopen;
  696.         XprIO->xpr_fclose        = xpr_fclose;
  697.         XprIO->xpr_fread        = xpr_fread;
  698.         XprIO->xpr_fwrite        = xpr_fwrite;
  699.         XprIO->xpr_sread        = xpr_sread;
  700.         XprIO->xpr_swrite        = xpr_swrite;
  701.         XprIO->xpr_sflush        = xpr_sflush;
  702.         XprIO->xpr_update        = xpr_update;
  703.         XprIO->xpr_chkabort        = xpr_chkabort;
  704.         XprIO->xpr_gets            = xpr_gets;
  705.         XprIO->xpr_setserial    = xpr_setserial;
  706.         XprIO->xpr_ffirst        = xpr_ffirst;
  707.         XprIO->xpr_fnext        = xpr_fnext;
  708.         XprIO->xpr_finfo        = xpr_finfo;
  709.         XprIO->xpr_fseek        = xpr_fseek;
  710.         XprIO->xpr_options        = xpr_options;
  711.         XprIO->xpr_unlink        = xpr_unlink;
  712.         XprIO->xpr_squery        = xpr_squery;
  713.         XprIO->xpr_getptr        = xpr_getptr;
  714.     #endif    /* USE_GLUE */
  715.  
  716.         /* No success so far */
  717.  
  718.     Result = FALSE;
  719.  
  720.         /* Try to open the library. */
  721.  
  722.     if(XProtocolBase = (struct Library *)OpenLibrary(ProtocolName,0))
  723.     {
  724.             /* Set up the library. */
  725.  
  726.         ClearSerial();
  727.  
  728.         TransferBits = XProtocolSetup(XprIO);
  729.  
  730.         SerWriteUpdate();
  731.  
  732.         RestartSerial();
  733.  
  734.         DeleteTransferPanel(TRUE);
  735.  
  736.             /* Successful initialization? */
  737.  
  738.         if(TransferBits & XPRS_SUCCESS)
  739.         {
  740.             strcpy(LastXprLibrary,ProtocolName);
  741.  
  742.             if(TransferBits & XPRS_HOSTNOWAIT)
  743.             {
  744.                 if(!HostReadBuffer)
  745.                     HostReadBuffer = AllocVecPooled(Config->SerialConfig->SerialBufferSize,MEMF_ANY);
  746.             }
  747.             else
  748.             {
  749.                 FreeVecPooled(HostReadBuffer);
  750.                 HostReadBuffer = NULL;
  751.             }
  752.  
  753.             strcpy(TransferProtocolName,&NameBuffer[3]);
  754.  
  755.             Result = TRUE;
  756.         }
  757.     }
  758.  
  759.     if(!Result)
  760.     {
  761.         ShowRequest(Window,LocaleString(MSG_GLOBAL_FAILED_TO_SET_UP_PROTOCOL_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),FilePart(ProtocolName));
  762.  
  763.         CloseLibrary(XProtocolBase);
  764.         XProtocolBase = NULL;
  765.  
  766.         SerWriteUpdate();
  767.  
  768.         LastXprLibrary[0] = 0;
  769.         TransferBits = 0;
  770.  
  771.         TransferProtocolName[0] = 0;
  772.     }
  773.  
  774.     ConTransferUpdate();
  775.  
  776.     SetTransferMenu(TRUE);
  777.  
  778.     return(Result);
  779. }
  780.  
  781.     /* CreateArgName(STRPTR String):
  782.      *
  783.      *    Create another node based upon a string given.
  784.      *    Encloses parameters in quotes if necessary and
  785.      *    `escapes' quotes.
  786.      */
  787.  
  788. STATIC struct Node *
  789. CreateArgName(STRPTR String)
  790. {
  791.     struct Node    *Node;
  792.     STRPTR         Index = String;
  793.     LONG         Len,NewLen;
  794.     BOOL          Quotes = FALSE;
  795.  
  796.     Len = NewLen = strlen(String);
  797.  
  798.     while(*Index)
  799.     {
  800.         if(*Index == '\"')
  801.             NewLen++;
  802.  
  803.         if(*Index == ' ' && !Quotes)
  804.         {
  805.             NewLen += 2;
  806.  
  807.             Quotes = TRUE;
  808.         }
  809.  
  810.         Index++;
  811.     }
  812.  
  813.     if(!Len)
  814.     {
  815.         NewLen += 2;
  816.  
  817.         Quotes = TRUE;
  818.     }
  819.  
  820.     if(NewLen > Len)
  821.     {
  822.         if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + NewLen + 1,MEMF_ANY))
  823.         {
  824.             STRPTR Dest;
  825.  
  826.             Node->ln_Name = (STRPTR)(Node + 1);
  827.  
  828.             Dest    = Node->ln_Name;
  829.             Index    = String;
  830.  
  831.             if(Quotes)
  832.                 *Dest++ = '\"';
  833.  
  834.             while(*Index)
  835.             {
  836.                 if(*Index == '\"')
  837.                     *Dest++ = '*';
  838.  
  839.                 *Dest++ = *Index++;
  840.             }
  841.  
  842.             if(Quotes)
  843.                 *Dest++ = '\"';
  844.  
  845.             *Dest = 0;
  846.         }
  847.     }
  848.     else
  849.     {
  850.         if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + Len + 1,MEMF_ANY))
  851.             strcpy(Node->ln_Name = (STRPTR)(Node + 1),String);
  852.     }
  853.  
  854.     return(Node);
  855. }
  856.  
  857.     /* BuildString():
  858.      *
  859.      *    Build a command line based upon a template and
  860.      *    existing file transfer info.
  861.      */
  862.  
  863. STATIC STRPTR
  864. BuildString(STRPTR Source,STRPTR From,STRPTR To,BYTE Type,BOOL ReceiveMode,STRPTR SingleFile,struct FileTransferInfo *Info,LONG *Error)
  865. {
  866.     struct List    *List;
  867.     STRPTR Result = NULL;
  868.  
  869.     if(Info)
  870.     {
  871.         if(!IsListEmpty((struct List *)Info))
  872.             Info->CurrentFile = (struct FileTransferNode *)Info->FileList.mlh_Head;
  873.         else
  874.             Info = NULL;
  875.     }
  876.  
  877.     *Error = 0;
  878.  
  879.     if(List = CreateList())
  880.     {
  881.         UBYTE LocalBuffer[MAX_FILENAME_LENGTH],TempBuffer[MAX_FILENAME_LENGTH];
  882.         struct FileRequester *FileRequest;
  883.         STRPTR Index,Dest;
  884.         struct Node *Node;
  885.  
  886.         Index = Source;
  887.         Dest = LocalBuffer;
  888.  
  889.         while(*Index && !(*Error))
  890.         {
  891.             if(*Index == '%')
  892.             {
  893.                 struct Node    *InsertHere = List->lh_TailPred;
  894.                 BOOL InsertBefore = TRUE;
  895.  
  896.                 Index++;
  897.  
  898.                 if(!(*Index))
  899.                 {
  900.                     *Dest = 0;
  901.  
  902.                     if(LocalBuffer[0])
  903.                     {
  904.                         if(Node = CreateNode(LocalBuffer))
  905.                         {
  906.                             AddTail(List,Node);
  907.  
  908.                             LocalBuffer[0] = 0;
  909.                         }
  910.                         else
  911.                             *Error = ERROR_NO_FREE_STORE;
  912.                     }
  913.  
  914.                     break;
  915.                 }
  916.  
  917.                 switch(*Index)
  918.                 {
  919.                     case 'f':
  920.  
  921.                         if(SingleFile)
  922.                         {
  923.                             if(Node = CreateArgName(SingleFile))
  924.                                 AddTail(List,Node);
  925.                             else
  926.                                 *Error = ERROR_NO_FREE_STORE;
  927.  
  928.                             SingleFile = NULL;
  929.  
  930.                             break;
  931.                         }
  932.  
  933.                         if(Info)
  934.                         {
  935.                             if(Node = CreateArgName(Info->CurrentFile->Name))
  936.                                 AddTail(List,Node);
  937.                             else
  938.                                 *Error = ERROR_NO_FREE_STORE;
  939.  
  940.                             if(Info->CurrentFile->MinNode.mln_Succ)
  941.                                 Info->CurrentFile = (struct FileTransferNode *)Info->CurrentFile->MinNode.mln_Succ;
  942.                             else
  943.                                 Info = NULL;
  944.  
  945.                             break;
  946.                         }
  947.  
  948.                         LT_LockWindow(Window);
  949.  
  950.                         if(ReceiveMode)
  951.                         {
  952.                             LimitedStrcpy(sizeof(TempBuffer),TempBuffer,To);
  953.  
  954.                             FileRequest = SaveFile(Window,LocaleString(MSG_TERMTRANSFER_DOWNLOAD_FILE_TXT + Type),LocaleString(MSG_TERMTRANSFER_RECEIVE_TXT),NULL,TempBuffer,sizeof(TempBuffer));
  955.                         }
  956.                         else
  957.                         {
  958.                             LimitedStrcpy(sizeof(TempBuffer),TempBuffer,From);
  959.  
  960.                             FileRequest = OpenSingleFile(Window,LocaleString(MSG_TERMTRANSFER_UPLOAD_FILE_TXT + Type),LocaleString(MSG_TERMTRANSFER_SEND_TXT),NULL,TempBuffer,sizeof(TempBuffer));
  961.                         }
  962.  
  963.                         if(FileRequest)
  964.                         {
  965.                             if(Node = CreateArgName(TempBuffer))
  966.                                 AddTail(List,Node);
  967.                             else
  968.                                 *Error = ERROR_NO_FREE_STORE;
  969.  
  970.                             FreeAslRequest(FileRequest);
  971.                         }
  972.                         else
  973.                             *Error = ERR_ABORTED;
  974.  
  975.                         LT_UnlockWindow(Window);
  976.  
  977.                         break;
  978.  
  979.                     case 'F':
  980.  
  981.                         if(SingleFile)
  982.                         {
  983.                             if(Node = CreateArgName(FilePart(SingleFile)))
  984.                                 AddTail(List,Node);
  985.                             else
  986.                                 *Error = ERROR_NO_FREE_STORE;
  987.  
  988.                             SingleFile = NULL;
  989.  
  990.                             break;
  991.                         }
  992.  
  993.                         if(Info)
  994.                         {
  995.                             if(Node = CreateArgName(FilePart(Info->CurrentFile->Name)))
  996.                                 AddTail(List,Node);
  997.                             else
  998.                                 *Error = ERROR_NO_FREE_STORE;
  999.  
  1000.                             if(Info->CurrentFile->MinNode.mln_Succ)
  1001.                                 Info->CurrentFile = (struct FileTransferNode *)Info->CurrentFile->MinNode.mln_Succ;
  1002.                             else
  1003.                                 Info = NULL;
  1004.  
  1005.                             break;
  1006.                         }
  1007.  
  1008.                         LT_LockWindow(Window);
  1009.  
  1010.                         if(ReceiveMode)
  1011.                         {
  1012.                             LimitedStrcpy(sizeof(TempBuffer),TempBuffer,To);
  1013.  
  1014.                             FileRequest = SaveFile(Window,LocaleString(MSG_TERMTRANSFER_DOWNLOAD_FILE_TXT + Type),LocaleString(MSG_TERMTRANSFER_RECEIVE_TXT),NULL,TempBuffer,sizeof(TempBuffer));
  1015.                         }
  1016.                         else
  1017.                         {
  1018.                             LimitedStrcpy(sizeof(TempBuffer),TempBuffer,From);
  1019.  
  1020.                             FileRequest = OpenSingleFile(Window,LocaleString(MSG_TERMTRANSFER_UPLOAD_FILE_TXT + Type),LocaleString(MSG_TERMTRANSFER_SEND_TXT),NULL,TempBuffer,sizeof(TempBuffer));
  1021.                         }
  1022.  
  1023.                         if(FileRequest)
  1024.                         {
  1025.                             if(Node = CreateArgName(FilePart(TempBuffer)))
  1026.                                 AddTail(List,Node);
  1027.                             else
  1028.                                 *Error = ERROR_NO_FREE_STORE;
  1029.  
  1030.                             FreeAslRequest(FileRequest);
  1031.                         }
  1032.                         else
  1033.                             *Error = ERR_ABORTED;
  1034.  
  1035.                         LT_UnlockWindow(Window);
  1036.  
  1037.                         break;
  1038.  
  1039.                     case 'm':
  1040.  
  1041.                         if(SingleFile)
  1042.                         {
  1043.                             if(Node = CreateArgName(SingleFile))
  1044.                                 AddTail(List,Node);
  1045.                             else
  1046.                                 *Error = ERROR_NO_FREE_STORE;
  1047.  
  1048.                             SingleFile = NULL;
  1049.  
  1050.                             break;
  1051.                         }
  1052.  
  1053.                         if(Info)
  1054.                         {
  1055.                             struct FileTransferNode *SomeNode;
  1056.  
  1057.                             for(SomeNode = Info->CurrentFile ; SomeNode->MinNode.mln_Succ && !(*Error) ; SomeNode = (struct FileTransferNode *)SomeNode->MinNode.mln_Succ)
  1058.                             {
  1059.                                 if(Node = CreateArgName(SomeNode->Name))
  1060.                                     AddTail(List,Node);
  1061.                                 else
  1062.                                     *Error = ERROR_NO_FREE_STORE;
  1063.                             }
  1064.  
  1065.                             Info = NULL;
  1066.  
  1067.                             break;
  1068.                         }
  1069.  
  1070.                         LT_LockWindow(Window);
  1071.  
  1072.                         if(ReceiveMode)
  1073.                         {
  1074.                             LimitedStrcpy(sizeof(TempBuffer),TempBuffer,To);
  1075.  
  1076.                             FileRequest = SaveFile(Window,LocaleString(MSG_TERMTRANSFER_DOWNLOAD_FILE_TXT + Type),LocaleString(MSG_TERMTRANSFER_RECEIVE_TXT),NULL,TempBuffer,sizeof(TempBuffer));
  1077.                         }
  1078.                         else
  1079.                         {
  1080.                             LimitedStrcpy(sizeof(TempBuffer),TempBuffer,From);
  1081.  
  1082.                             FileRequest = OpenSeveralFiles(Window,LocaleString(MSG_TERMTRANSFER_UPLOAD_FILE_TXT + Type),LocaleString(MSG_TERMTRANSFER_SEND_TXT),NULL,TempBuffer,sizeof(TempBuffer));
  1083.                         }
  1084.  
  1085.                         LT_UnlockWindow(Window);
  1086.  
  1087.                         if(FileRequest)
  1088.                         {
  1089.                             LONG i;
  1090.  
  1091.                             if(TempBuffer[0] && FileRequest->fr_NumArgs == 1)
  1092.                             {
  1093.                                 if(Node = CreateArgName(TempBuffer))
  1094.                                 {
  1095.                                     AddTail(List,Node);
  1096.  
  1097.                                     break;
  1098.                                 }
  1099.                                 else
  1100.                                     *Error = ERROR_NO_FREE_STORE;
  1101.                             }
  1102.  
  1103.                             for(i = 0 ; i < FileRequest->fr_NumArgs && !(*Error) ; i++)
  1104.                             {
  1105.                                 if(FileRequest->fr_ArgList[i].wa_Lock)
  1106.                                 {
  1107.                                     if(NameFromLock(FileRequest->fr_ArgList[i].wa_Lock,TempBuffer,sizeof(TempBuffer)))
  1108.                                     {
  1109.                                         if(AddPart(TempBuffer,FileRequest->fr_ArgList[i].wa_Name,sizeof(TempBuffer)))
  1110.                                         {
  1111.                                             if(Node = CreateArgName(TempBuffer))
  1112.                                                 AddTail(List,Node);
  1113.                                             else
  1114.                                                 *Error = ERROR_NO_FREE_STORE;
  1115.                                         }
  1116.                                         else
  1117.                                             *Error = IoErr();
  1118.                                     }
  1119.                                     else
  1120.                                         *Error = IoErr();
  1121.                                 }
  1122.                                 else
  1123.                                 {
  1124.                                     LimitedStrcpy(sizeof(TempBuffer),TempBuffer,FileRequest->fr_Drawer);
  1125.  
  1126.                                     if(AddPart(TempBuffer,FileRequest->fr_ArgList[i].wa_Name,sizeof(TempBuffer)))
  1127.                                     {
  1128.                                         if(Node = CreateArgName(TempBuffer))
  1129.                                             AddTail(List,Node);
  1130.                                         else
  1131.                                             *Error = ERROR_NO_FREE_STORE;
  1132.                                     }
  1133.                                     else
  1134.                                         *Error = IoErr();
  1135.                                 }
  1136.                             }
  1137.  
  1138.                             FreeAslRequest(FileRequest);
  1139.                         }
  1140.                         else
  1141.                             *Error = ERR_ABORTED;
  1142.  
  1143.                         break;
  1144.  
  1145.                     case 'M':
  1146.  
  1147.                         if(SingleFile)
  1148.                         {
  1149.                             if(Node = CreateArgName(FilePart(SingleFile)))
  1150.                                 AddTail(List,Node);
  1151.                             else
  1152.                                 *Error = ERROR_NO_FREE_STORE;
  1153.  
  1154.                             SingleFile = NULL;
  1155.  
  1156.                             break;
  1157.                         }
  1158.  
  1159.                         if(Info)
  1160.                         {
  1161.                             struct FileTransferNode *SomeNode;
  1162.  
  1163.                             for(SomeNode = Info->CurrentFile ; SomeNode->MinNode.mln_Succ && !(*Error) ; SomeNode = (struct FileTransferNode *)SomeNode->MinNode.mln_Succ)
  1164.                             {
  1165.                                 if(Node = CreateArgName(FilePart(SomeNode->Name)))
  1166.                                     AddTail(List,Node);
  1167.                                 else
  1168.                                     *Error = ERROR_NO_FREE_STORE;
  1169.                             }
  1170.  
  1171.                             Info = NULL;
  1172.  
  1173.                             break;
  1174.                         }
  1175.  
  1176.                         LT_LockWindow(Window);
  1177.  
  1178.                         if(ReceiveMode)
  1179.                         {
  1180.                             LimitedStrcpy(sizeof(TempBuffer),TempBuffer,To);
  1181.  
  1182.                             FileRequest = SaveFile(Window,LocaleString(MSG_TERMTRANSFER_DOWNLOAD_FILE_TXT + Type),LocaleString(MSG_TERMTRANSFER_RECEIVE_TXT),NULL,TempBuffer,sizeof(TempBuffer));
  1183.                         }
  1184.                         else
  1185.                         {
  1186.                             LimitedStrcpy(sizeof(TempBuffer),TempBuffer,From);
  1187.  
  1188.                             FileRequest = OpenSeveralFiles(Window,LocaleString(MSG_TERMTRANSFER_UPLOAD_FILE_TXT + Type),LocaleString(MSG_TERMTRANSFER_SEND_TXT),NULL,TempBuffer,sizeof(TempBuffer));
  1189.                         }
  1190.  
  1191.                         LT_UnlockWindow(Window);
  1192.  
  1193.                         if(FileRequest)
  1194.                         {
  1195.                             LONG i;
  1196.  
  1197.                             if(TempBuffer[0] && FileRequest->fr_NumArgs == 1)
  1198.                             {
  1199.                                 if(Node = CreateArgName(FilePart(TempBuffer)))
  1200.                                 {
  1201.                                     AddTail(List,Node);
  1202.  
  1203.                                     break;
  1204.                                 }
  1205.                                 else
  1206.                                     *Error = ERROR_NO_FREE_STORE;
  1207.                             }
  1208.  
  1209.                             for(i = 0 ; i < FileRequest->fr_NumArgs && !(*Error) ; i++)
  1210.                             {
  1211.                                 if(FileRequest->fr_ArgList[i].wa_Lock)
  1212.                                 {
  1213.                                     if(AddPart(TempBuffer,FileRequest->fr_ArgList[i].wa_Name,sizeof(TempBuffer)))
  1214.                                     {
  1215.                                         if(Node = CreateArgName(TempBuffer))
  1216.                                             AddTail(List,Node);
  1217.                                         else
  1218.                                             *Error = ERROR_NO_FREE_STORE;
  1219.                                     }
  1220.                                     else
  1221.                                         *Error = IoErr();
  1222.                                 }
  1223.                                 else
  1224.                                 {
  1225.                                     if(Node = CreateArgName(FileRequest->fr_ArgList[i].wa_Name))
  1226.                                         AddTail(List,Node);
  1227.                                     else
  1228.                                         *Error = ERROR_NO_FREE_STORE;
  1229.                                 }
  1230.                             }
  1231.  
  1232.                             FreeAslRequest(FileRequest);
  1233.                         }
  1234.                         else
  1235.                             *Error = ERR_ABORTED;
  1236.  
  1237.                         break;
  1238.  
  1239.                     case 'b':
  1240.                     case 'B':
  1241.  
  1242.                         if(Node = CreateNodeArgs("%ld",Config->SerialConfig->BaudRate))
  1243.                             AddTail(List,Node);
  1244.                         else
  1245.                             *Error = ERROR_NO_FREE_STORE;
  1246.  
  1247.                         break;
  1248.  
  1249.                     case 'c':
  1250.                     case 'C':
  1251.  
  1252.                         if(Node = CreateNodeArgs("%ld",DTERate ? DTERate : Config->SerialConfig->BaudRate))
  1253.                             AddTail(List,Node);
  1254.                         else
  1255.                             *Error = ERROR_NO_FREE_STORE;
  1256.  
  1257.                         break;
  1258.  
  1259.                     case 'p':
  1260.                     case 'P':
  1261.  
  1262.                         if(Node = CreateArgName(RexxPortName))
  1263.                             AddTail(List,Node);
  1264.                         else
  1265.                             *Error = ERROR_NO_FREE_STORE;
  1266.  
  1267.                         break;
  1268.  
  1269.                     case 'd':
  1270.                     case 'D':
  1271.  
  1272.                         if(Node = CreateArgName(Config->SerialConfig->SerialDevice))
  1273.                             AddTail(List,Node);
  1274.                         else
  1275.                             *Error = ERROR_NO_FREE_STORE;
  1276.  
  1277.                         break;
  1278.  
  1279.                     case 'u':
  1280.                     case 'U':
  1281.  
  1282.                         if(Node = CreateNodeArgs("%ld",Config->SerialConfig->UnitNumber))
  1283.                             AddTail(List,Node);
  1284.                         else
  1285.                             *Error = ERROR_NO_FREE_STORE;
  1286.  
  1287.                         break;
  1288.  
  1289.                     case '<':
  1290.  
  1291.                         if(Node = CreateArgName(From))
  1292.                             AddTail(List,Node);
  1293.                         else
  1294.                             *Error = ERROR_NO_FREE_STORE;
  1295.  
  1296.                         break;
  1297.  
  1298.                     case '>':
  1299.  
  1300.                         if(Node = CreateArgName(To))
  1301.                             AddTail(List,Node);
  1302.                         else
  1303.                             *Error = ERROR_NO_FREE_STORE;
  1304.  
  1305.                         break;
  1306.  
  1307.                     case 's':
  1308.                     case 'S':
  1309.  
  1310.                         if(!GetPubScreenName(Window->WScreen,TempBuffer))
  1311.                             TempBuffer[0] = 0;
  1312.  
  1313.                         if(Node = CreateArgName(TempBuffer))
  1314.                             AddTail(List,Node);
  1315.                         else
  1316.                             *Error = ERROR_NO_FREE_STORE;
  1317.  
  1318.                         break;
  1319.  
  1320.                     default:
  1321.  
  1322.                         *Dest = *Index;
  1323.  
  1324.                         InsertBefore = FALSE;
  1325.  
  1326.                         break;
  1327.                 }
  1328.  
  1329.                 if(InsertBefore && Node)
  1330.                 {
  1331.                     struct Node *OtherNode;
  1332.  
  1333.                     *Dest = 0;
  1334.  
  1335.                     if(LocalBuffer[0])
  1336.                     {
  1337.                         if(OtherNode = CreateNode(LocalBuffer))
  1338.                         {
  1339.                             Insert(List,OtherNode,InsertHere);
  1340.  
  1341.                             LocalBuffer[0] = 0;
  1342.                         }
  1343.                         else
  1344.                             *Error = ERROR_NO_FREE_STORE;
  1345.                     }
  1346.  
  1347.                     Dest = LocalBuffer;
  1348.                 }
  1349.             }
  1350.             else
  1351.                 *Dest++ = *Index;
  1352.  
  1353.             Index++;
  1354.         }
  1355.  
  1356.         *Dest = 0;
  1357.  
  1358.         if(LocalBuffer[0] && !(*Error))
  1359.         {
  1360.             if(Node = CreateNode(LocalBuffer))
  1361.                 AddTail(List,Node);
  1362.             else
  1363.                 *Error = ERROR_NO_FREE_STORE;
  1364.         }
  1365.  
  1366.         if(!(*Error))
  1367.         {
  1368.             if(!IsListEmpty(List))
  1369.             {
  1370.                 LONG Total = 0,Len;
  1371.  
  1372.                 for(Node = List->lh_Head ; Node->ln_Succ ; Node = Node->ln_Succ)
  1373.                     Total += strlen(Node->ln_Name) + 1;
  1374.  
  1375.                 if(Result = (STRPTR)AllocVecPooled(Total,MEMF_ANY))
  1376.                 {
  1377.                     STRPTR Buffer = Result;
  1378.  
  1379.                     for(Node = List->lh_Head ; Node->ln_Succ ; Node = Node->ln_Succ)
  1380.                     {
  1381.                         Len = strlen(Node->ln_Name);
  1382.  
  1383.                         CopyMem(Node->ln_Name,Buffer,Len);
  1384.  
  1385.                         Buffer += Len;
  1386.  
  1387.                         *Buffer++ = ' ';
  1388.                     }
  1389.  
  1390.                     Buffer[-1] = 0;
  1391.                 }
  1392.             }
  1393.             else
  1394.                 Result = "";
  1395.         }
  1396.  
  1397.         DeleteList(List);
  1398.     }
  1399.     else
  1400.         *Error = ERROR_NO_FREE_STORE;
  1401.  
  1402.     return(Result);
  1403. }
  1404.  
  1405.     /* ReplaceName(STRPTR Original):
  1406.      *
  1407.      *    Replace a filename with a mangled version for
  1408.      *    file uploads.
  1409.      */
  1410.  
  1411. STATIC STRPTR
  1412. ReplaceName(STRPTR Source)
  1413. {
  1414.     if(Config->TransferConfig->MangleFileNames)
  1415.     {
  1416.         UBYTE LocalName[MAX_FILENAME_LENGTH],*Char;
  1417.  
  1418.         LimitedStrcpy(sizeof(OriginalName),OriginalName,Source);
  1419.  
  1420.         ShrinkName(FilePart(Source),LocalName,12,TRUE);
  1421.  
  1422.         LimitedStrcpy(sizeof(ShrunkenName),ShrunkenName,Source);
  1423.  
  1424.         Char = PathPart(ShrunkenName);
  1425.  
  1426.         *Char = 0;
  1427.  
  1428.         if(AddPart(ShrunkenName,LocalName,sizeof(ShrunkenName)))
  1429.             return(ShrunkenName);
  1430.     }
  1431.  
  1432.     OriginalName[0] = 0;
  1433.     return(Source);
  1434. }
  1435.  
  1436.     /* CommonStartSendXPR():
  1437.      *
  1438.      *    Start sending files using the XPR protocol.
  1439.      */
  1440.  
  1441. STATIC VOID
  1442. CommonStartSendXPR(LONG Type,BOOL IsBinary,BOOL WaitForIt)
  1443. {
  1444.     PushStatus(STATUS_UPLOAD);
  1445.  
  1446.     if(TransferPanel(LocaleString(MSG_TERMTRANSFER_UPLOAD_FILE_TXT + (Type - TRANSFER_BINARY))))
  1447.     {
  1448.         ClearSerial();
  1449.  
  1450.         LogAction(LocaleString(MSG_TERMTRANSFER_LOGMSG_INITIATE_UPLOAD_TXT),LocaleString(MSG_TERMTRANSFER_BINARY_TXT + (Type - TRANSFER_BINARY)));
  1451.  
  1452.         TransferFailed = StartSend(IsBinary);
  1453.  
  1454.             /* Tell the user what happened */
  1455.  
  1456.         if(TransferFailed || TransferAborted)
  1457.             Say(LocaleString(MSG_GLOBAL_TRANSFER_FAILED_OR_ABORTED_TXT));
  1458.         else
  1459.             Say(LocaleString(MSG_GLOBAL_TRANSFER_COMPLETED_TXT));
  1460.  
  1461.         if(TransferFailed || TransferError)
  1462.         {
  1463.             if(Config->TransferConfig->TransferNotification == XFERNOTIFY_ALWAYS || Config->TransferConfig->TransferNotification == XFERNOTIFY_END)
  1464.                 WakeUp(TransferWindow,SOUND_BADTRANSFER);
  1465.  
  1466.             DeleteTransferPanel(WaitForIt);
  1467.         }
  1468.         else
  1469.         {
  1470.             if(TransferWindow)
  1471.             {
  1472.                 if(Config->TransferConfig->TransferNotification == XFERNOTIFY_ALWAYS || Config->TransferConfig->TransferNotification == XFERNOTIFY_END)
  1473.                     WakeUp(TransferWindow,SOUND_GOODTRANSFER);
  1474.  
  1475.                 DelayTime(2,0);
  1476.             }
  1477.  
  1478.             DeleteTransferPanel(FALSE);
  1479.         }
  1480.  
  1481.         RestartSerial();
  1482.     }
  1483.  
  1484.     PopStatus();
  1485. }
  1486.  
  1487.     /* CommonSendXPRCleanup(BOOL WaitForIt):
  1488.      *
  1489.      *    Do the cleanup work after a file transfer has finished.
  1490.      */
  1491.  
  1492. STATIC VOID
  1493. CommonSendXPRCleanup(BOOL WaitForIt)
  1494. {
  1495.     if(SendAbort)
  1496.     {
  1497.         CancelZModem();
  1498.         SendAbort = FALSE;
  1499.     }
  1500.  
  1501.     ReleaseWindows();
  1502.  
  1503.     Uploading = FALSE;
  1504.  
  1505.     if(WaitForIt)
  1506.     {
  1507.         if(Config->CommandConfig->UploadMacro[0])
  1508.             SerialCommand(Config->CommandConfig->UploadMacro);
  1509.     }
  1510.  
  1511.     DidTransfer = FALSE;
  1512. }
  1513.  
  1514.     /* CommonStartReceiveXPR():
  1515.      *
  1516.      *    Start receiving files using the XPR protocol.
  1517.      */
  1518.  
  1519. STATIC VOID
  1520. CommonStartReceiveXPR(LONG Type,BOOL IsBinary,BOOL WaitForIt)
  1521. {
  1522.     PushStatus(STATUS_DOWNLOAD);
  1523.  
  1524.         /* Open the transfer panel. */
  1525.  
  1526.     if(TransferPanel(LocaleString(MSG_TERMTRANSFER_DOWNLOAD_FILE_TXT + (Type - TRANSFER_BINARY))))
  1527.     {
  1528.         ClearSerial();
  1529.  
  1530.         LogAction(LocaleString(MSG_TERMTRANSFER_LOGMSG_INITIATE_DOWNLOAD_TXT),LocaleString(MSG_TERMTRANSFER_BINARY_TXT + (Type - TRANSFER_BINARY)));
  1531.  
  1532.             /* Receive the file. */
  1533.  
  1534.         TransferFailed = StartReceive(IsBinary);
  1535.  
  1536.         if(TransferAborted || TransferFailed)
  1537.             Say(LocaleString(MSG_GLOBAL_TRANSFER_FAILED_OR_ABORTED_TXT));
  1538.         else
  1539.             Say(LocaleString(MSG_GLOBAL_TRANSFER_COMPLETED_TXT));
  1540.  
  1541.         if(TransferFailed || TransferError)
  1542.         {
  1543.             if(Config->TransferConfig->TransferNotification == XFERNOTIFY_ALWAYS || Config->TransferConfig->TransferNotification == XFERNOTIFY_END)
  1544.                 WakeUp(TransferWindow,SOUND_BADTRANSFER);
  1545.  
  1546.             DeleteTransferPanel(WaitForIt);
  1547.         }
  1548.         else
  1549.         {
  1550.             if(TransferWindow)
  1551.             {
  1552.                 if(Config->TransferConfig->TransferNotification == XFERNOTIFY_ALWAYS || Config->TransferConfig->TransferNotification == XFERNOTIFY_END)
  1553.                     WakeUp(TransferWindow,SOUND_GOODTRANSFER);
  1554.  
  1555.                 DelayTime(2,0);
  1556.             }
  1557.  
  1558.             DeleteTransferPanel(FALSE);
  1559.         }
  1560.  
  1561.             /* Queue another read
  1562.              * request.
  1563.              */
  1564.  
  1565.         RestartSerial();
  1566.     }
  1567.  
  1568.     PopStatus();
  1569. }
  1570.  
  1571.     /* TransferCompare(struct FileTransferNode **A,struct FileTransferNode **B):
  1572.      *
  1573.      *    Local subroutine required by QuickSort().
  1574.      */
  1575.  
  1576. STATIC LONG
  1577. TransferCompare(struct FileTransferNode **A,struct FileTransferNode **B)
  1578. {
  1579.     if((*A)->Size > (*B)->Size)
  1580.         return(-1);
  1581.     else
  1582.     {
  1583.         if((*A)->Size < (*B)->Size)
  1584.             return(1);
  1585.         else
  1586.             return(Stricmp(FilePart((*A)->Name),FilePart((*B)->Name)));
  1587.     }
  1588. }
  1589.  
  1590.     /* FreeFileTransferInfo(struct FileTransferInfo *Info):
  1591.      *
  1592.      *    Free a file transfer info list as allocated
  1593.      *    by AllocFileTransferInfo() and AddFileTransferNode().
  1594.      */
  1595.  
  1596. VOID
  1597. FreeFileTransferInfo(struct FileTransferInfo *Info)
  1598. {
  1599.     if(Info)
  1600.     {
  1601.         struct FileTransferNode *Node,*Next;
  1602.  
  1603.         for(Node = (struct FileTransferNode *)Info->FileList.mlh_Head ; Next = (struct FileTransferNode *)Node->MinNode.mln_Succ ; Node = Next)
  1604.             FreeVecPooled(Node);
  1605.  
  1606.         FreeVecPooled(Info);
  1607.     }
  1608. }
  1609.  
  1610.     /* AllocFileTransferInfo():
  1611.      *
  1612.      *    Allocate a FileTransferInfo structure for use with
  1613.      *    AddFileTransferNode().
  1614.      */
  1615.  
  1616. struct FileTransferInfo *
  1617. AllocFileTransferInfo()
  1618. {
  1619.     struct FileTransferInfo *Info;
  1620.  
  1621.     if(Info = (struct FileTransferInfo *)AllocVecPooled(sizeof(struct FileTransferInfo),MEMF_ANY | MEMF_CLEAR))
  1622.     {
  1623.         NewList((struct List *)&Info->FileList);
  1624.  
  1625.         return(Info);
  1626.     }
  1627.  
  1628.     return(NULL);
  1629. }
  1630.  
  1631.     /* AddFileTransferNode(struct FileTransferInfo *Info,STRPTR Name,ULONG Size):
  1632.      *
  1633.      *    Allocate a file transfer information node.
  1634.      */
  1635.  
  1636. BOOL
  1637. AddFileTransferNode(struct FileTransferInfo *Info,STRPTR Name,ULONG Size)
  1638. {
  1639.     struct FileTransferNode *Node;
  1640.  
  1641.     if(Node = (struct FileTransferNode *)AllocVecPooled(sizeof(struct FileTransferNode) + strlen(Name) + 1,MEMF_ANY))
  1642.     {
  1643.         Node->Size    = Size;
  1644.         Node->Name    = (STRPTR)(Node + 1);
  1645.  
  1646.         strcpy(Node->Name,Name);
  1647.  
  1648.         AddTail((struct List *)&Info->FileList,(struct Node *)Node);
  1649.  
  1650.         Info->TotalSize += Size;
  1651.  
  1652.         Info->TotalFiles++;
  1653.  
  1654.         return(TRUE);
  1655.     }
  1656.     else
  1657.         return(FALSE);
  1658. }
  1659.  
  1660.     /* ReadyFileTransferInfo(struct FileTransferInfo *Info,BOOL SortIt):
  1661.      *
  1662.      *    Sorts the file transfer information list in ascending
  1663.      *    order, but makes sure that the files are sorted
  1664.      *    in descending order (i.e. the larger files come
  1665.      *    first and files of equal size are sorted
  1666.      *    lexically).
  1667.      */
  1668.  
  1669. VOID
  1670. ReadyFileTransferInfo(struct FileTransferInfo *Info,BOOL SortIt)
  1671. {
  1672.     if(Info->TotalFiles > 1 && SortIt)
  1673.     {
  1674.         struct FileTransferNode **NodeTable;
  1675.  
  1676.         if(NodeTable = (struct FileTransferNode **)AllocVecPooled(sizeof(struct FileTransferNode *) * Info->TotalFiles,MEMF_ANY))
  1677.         {
  1678.             struct FileTransferNode *Node;
  1679.             LONG i;
  1680.  
  1681.             for(Node = (struct FileTransferNode *)Info->FileList.mlh_Head, i = 0 ; Node->MinNode.mln_Succ ; Node = (struct FileTransferNode *)Node->MinNode.mln_Succ, i++)
  1682.                 NodeTable[i] = Node;
  1683.  
  1684.             qsort(NodeTable,Info->TotalFiles,sizeof(struct FileTransferNode *),(SORTFUNC)TransferCompare);
  1685.  
  1686.             NewList((struct List *)&Info->FileList);
  1687.  
  1688.             for(i = 0 ; i < Info->TotalFiles ; i++)
  1689.                 AddTail((struct List *)&Info->FileList,(struct Node *)NodeTable[i]);
  1690.  
  1691.             FreeVecPooled(NodeTable);
  1692.         }
  1693.     }
  1694.  
  1695.     Info->DoneSize    = 0;
  1696.     Info->DoneFiles    = 0;
  1697.  
  1698.     Info->CurrentFile    = (struct FileTransferNode *)Info->FileList.mlh_Head;
  1699.     Info->CurrentSize    = Info->CurrentFile->Size;
  1700. }
  1701.  
  1702.     /* BuildFileTransferInfo(struct FileRequester *FileRequester):
  1703.      *
  1704.      *    Build a file transfer information list from
  1705.      *    information provided by a FileRequester structure.
  1706.      */
  1707.  
  1708. struct FileTransferInfo *
  1709. BuildFileTransferInfo(struct FileRequester *FileRequester)
  1710. {
  1711.     struct FileTransferInfo *Info;
  1712.     LONG FilesFound;
  1713.  
  1714.     FilesFound = 0;
  1715.  
  1716.     if(Info = AllocFileTransferInfo())
  1717.     {
  1718.         BOOL Success = FALSE;
  1719.         BPTR NewLock,OldLock;
  1720.  
  1721.         if(NewLock = Lock(FileRequester->fr_Drawer,ACCESS_READ))
  1722.         {
  1723.             OldLock = CurrentDir(NewLock);
  1724.  
  1725.             if(FileRequester->fr_NumArgs)
  1726.             {
  1727.                 struct WBArg *ArgList;
  1728.                 BPTR FileLock;
  1729.                 LONG i;
  1730.                 D_S(struct FileInfoBlock,FileInfo);
  1731.  
  1732.                 ArgList = FileRequester->fr_ArgList;
  1733.                 Success = TRUE;
  1734.  
  1735.                 for(i = 0 ; Success && i < FileRequester->fr_NumArgs ; i++)
  1736.                 {
  1737.                     if(ArgList[i].wa_Name)
  1738.                     {
  1739.                         if(ArgList[i].wa_Lock)
  1740.                         {
  1741.                             CurrentDir(ArgList[i].wa_Lock);
  1742.  
  1743.                             if(FileLock = Lock(ArgList[i].wa_Name,ACCESS_READ))
  1744.                             {
  1745.                                 if(Examine(FileLock,FileInfo))
  1746.                                 {
  1747.                                     if(FileInfo->fib_DirEntryType < 0)
  1748.                                     {
  1749.                                         UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
  1750.  
  1751.                                         if(NameFromLock(FileLock,LocalBuffer,sizeof(LocalBuffer)))
  1752.                                         {
  1753.                                             if(!AddFileTransferNode(Info,LocalBuffer,FileInfo->fib_Size))
  1754.                                                 Success = FALSE;
  1755.                                             else
  1756.                                                 FilesFound++;
  1757.                                         }
  1758.                                     }
  1759.                                 }
  1760.  
  1761.                                 UnLock(FileLock);
  1762.                             }
  1763.  
  1764.                             CurrentDir(NewLock);
  1765.                         }
  1766.                         else
  1767.                         {
  1768.                             if(FileLock = Lock(ArgList[i].wa_Name,ACCESS_READ))
  1769.                             {
  1770.                                 if(Examine(FileLock,FileInfo))
  1771.                                 {
  1772.                                     if(FileInfo->fib_DirEntryType < 0)
  1773.                                     {
  1774.                                         UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
  1775.  
  1776.                                         if(NameFromLock(FileLock,LocalBuffer,sizeof(LocalBuffer)))
  1777.                                         {
  1778.                                             if(!AddFileTransferNode(Info,LocalBuffer,FileInfo->fib_Size))
  1779.                                                 Success = FALSE;
  1780.                                             else
  1781.                                                 FilesFound++;
  1782.                                         }
  1783.                                     }
  1784.                                 }
  1785.  
  1786.                                 UnLock(FileLock);
  1787.                             }
  1788.                         }
  1789.                     }
  1790.                 }
  1791.             }
  1792.             else
  1793.             {
  1794.                 struct AnchorPath *Anchor;
  1795.                 STRPTR FileName;
  1796.  
  1797.                 if(FileRequester->fr_NumArgs > 1 && FileRequester->fr_ArgList)
  1798.                     FileName = FileRequester->fr_ArgList->wa_Name;
  1799.                 else
  1800.                     FileName = FileRequester->fr_File;
  1801.  
  1802.                 if(Anchor = (struct AnchorPath *)AllocVecPooled(sizeof(struct AnchorPath),MEMF_ANY | MEMF_CLEAR))
  1803.                 {
  1804.                     if(!MatchFirst(FileName,Anchor))
  1805.                     {
  1806.                         Success = TRUE;
  1807.  
  1808.                         if(Anchor->ap_Info.fib_DirEntryType < 0)
  1809.                         {
  1810.                             UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
  1811.  
  1812.                             if(NameFromLock(NewLock,LocalBuffer,sizeof(LocalBuffer)))
  1813.                             {
  1814.                                 if(AddPart(LocalBuffer,Anchor->ap_Info.fib_FileName,sizeof(LocalBuffer)))
  1815.                                 {
  1816.                                     if(!AddFileTransferNode(Info,LocalBuffer,Anchor->ap_Info.fib_Size))
  1817.                                         Success = FALSE;
  1818.                                     else
  1819.                                         FilesFound++;
  1820.                                 }
  1821.                             }
  1822.                         }
  1823.  
  1824.                         if(Success)
  1825.                         {
  1826.                             while(!MatchNext(Anchor))
  1827.                             {
  1828.                                 UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
  1829.  
  1830.                                 if(NameFromLock(NewLock,LocalBuffer,sizeof(LocalBuffer)))
  1831.                                 {
  1832.                                     if(AddPart(LocalBuffer,Anchor->ap_Info.fib_FileName,sizeof(LocalBuffer)))
  1833.                                     {
  1834.                                         if(!AddFileTransferNode(Info,LocalBuffer,Anchor->ap_Info.fib_Size))
  1835.                                         {
  1836.                                             Success = FALSE;
  1837.  
  1838.                                             break;
  1839.                                         }
  1840.                                         else
  1841.                                             FilesFound++;
  1842.                                     }
  1843.                                 }
  1844.                             }
  1845.                         }
  1846.  
  1847.                         if(IoErr() != ERROR_NO_MORE_ENTRIES)
  1848.                             Success = FALSE;
  1849.                     }
  1850.  
  1851.                     MatchEnd(Anchor);
  1852.  
  1853.                     FreeVecPooled(Anchor);
  1854.                 }
  1855.             }
  1856.  
  1857.             UnLock(CurrentDir(OldLock));
  1858.         }
  1859.  
  1860.         if(Success && FilesFound)
  1861.         {
  1862.             ReadyFileTransferInfo(Info,TRUE);
  1863.  
  1864.             return(Info);
  1865.         }
  1866.         else
  1867.             FreeFileTransferInfo(Info);
  1868.     }
  1869.  
  1870.     return(NULL);
  1871. }
  1872.  
  1873. VOID
  1874. StartReceiveXPR_File(LONG Type,STRPTR Name,BOOL WaitForIt)
  1875. {
  1876.     CommonStartReceive(Type,Name,WaitForIt);
  1877. }
  1878.  
  1879. VOID
  1880. StartReceiveXPR_AskForFile(LONG Type,BOOL WaitForIt)
  1881. {
  1882.     CommonStartReceive(Type,NULL,WaitForIt);
  1883. }
  1884.  
  1885. BOOL
  1886. StartSendXPR_File(LONG Type,STRPTR TheFile,BOOL WaitForIt)
  1887. {
  1888.     return(CommonStartSend(Type,TheFile,NULL,WaitForIt));
  1889. }
  1890.  
  1891. BOOL
  1892. StartSendXPR_AskForFile(LONG Type,BOOL WaitForIt)
  1893. {
  1894.     return(CommonStartSend(Type,NULL,NULL,WaitForIt));
  1895. }
  1896.  
  1897. BOOL
  1898. StartSendXPR_FromList(LONG Type,BOOL WaitForIt)
  1899. {
  1900.     return(CommonStartSend(Type,NULL,&FileTransferInfo,WaitForIt));
  1901. }
  1902.  
  1903.     /* ResetProtocol():
  1904.      *
  1905.      *    Return to the previously selected file
  1906.      *    transfer protocol.
  1907.      */
  1908.  
  1909. VOID
  1910. ResetProtocol()
  1911. {
  1912.     ChangeProtocol(NULL,XFER_DEFAULT);
  1913. }
  1914.  
  1915.     /* SaveProtocolOpts():
  1916.      *
  1917.      *    Save the current protocol settings to an environment variable.
  1918.      */
  1919.  
  1920. VOID
  1921. SaveProtocolOpts()
  1922. {
  1923.         /* It's time to save the altered options. */
  1924.  
  1925.     if(NewOptions && XProtocolBase)
  1926.     {
  1927.         UBYTE NameBuffer[MAX_FILENAME_LENGTH];
  1928.  
  1929.             /* Strip the `.library' part. */
  1930.  
  1931.         StripLibrary(LastXprLibrary,NameBuffer,sizeof(NameBuffer));
  1932.  
  1933.             /* Cause the xpr.library to prompt for
  1934.              * input. We expect the library to fill
  1935.              * the prompt string with the default
  1936.              * settings. The resulting string is
  1937.              * intercepted by xpr_stealopts, saved
  1938.              * to an environment variable and will
  1939.              * serve as a reinitialization string
  1940.              * later.
  1941.              */
  1942.  
  1943.         XprIO->xpr_filename        = NULL;
  1944.         XprIO->xpr_extension    = 0;
  1945.  
  1946.         #ifdef USE_GLUE
  1947.             XprIO->xpr_gets            = xpr_stealopts_glue;
  1948.             XprIO->xpr_options        = NULL;
  1949.         #else
  1950.             XprIO->xpr_gets            = xpr_stealopts;
  1951.             XprIO->xpr_options        = NULL;
  1952.         #endif    /* USE_GLUE */
  1953.  
  1954.         ClearSerial();
  1955.  
  1956.         XProtocolSetup(XprIO);
  1957.  
  1958.         DeleteTransferPanel(FALSE);
  1959.  
  1960.             /* Save the options in case anything goes
  1961.              * wrong.
  1962.              */
  1963.  
  1964.         NewOptions = FALSE;
  1965.  
  1966.         SetEnvDOS(NameBuffer,ProtocolOptsBuffer);
  1967.  
  1968.             /* Reinitialize the library. */
  1969.  
  1970.         XprIO->xpr_filename        = ProtocolOptsBuffer;
  1971.         XprIO->xpr_extension    = 4;
  1972.  
  1973.         #ifdef USE_GLUE
  1974.             XprIO->xpr_gets            = xpr_gets_glue;
  1975.             XprIO->xpr_options        = xpr_options_glue;
  1976.         #else
  1977.             XprIO->xpr_gets            = xpr_gets;
  1978.             XprIO->xpr_options        = xpr_options;
  1979.         #endif    /* USE_GLUE */
  1980.  
  1981.         XProtocolSetup(XprIO);
  1982.  
  1983.         RestartSerial();
  1984.  
  1985.         DeleteTransferPanel(FALSE);
  1986.     }
  1987. }
  1988.  
  1989.     /* TransferCleanup():
  1990.      *
  1991.      *    We did a file transfer (auto-download?) and
  1992.      *    will need to close the transfer window.
  1993.      */
  1994.  
  1995. VOID
  1996. TransferCleanup()
  1997. {
  1998.     if(DidTransfer)
  1999.     {
  2000.         if(TransferFailed || TransferError)
  2001.         {
  2002.             if(Config->TransferConfig->TransferNotification == XFERNOTIFY_ALWAYS || Config->TransferConfig->TransferNotification == XFERNOTIFY_END)
  2003.                 WakeUp(TransferWindow,SOUND_BADTRANSFER);
  2004.  
  2005.             DeleteTransferPanel(TRUE);
  2006.         }
  2007.         else
  2008.         {
  2009.             if(TransferWindow)
  2010.             {
  2011.                 if(Config->TransferConfig->TransferNotification == XFERNOTIFY_ALWAYS || Config->TransferConfig->TransferNotification == XFERNOTIFY_END)
  2012.                     WakeUp(TransferWindow,SOUND_GOODTRANSFER);
  2013.  
  2014.                 DelayTime(2,0);
  2015.             }
  2016.  
  2017.             DeleteTransferPanel(FALSE);
  2018.         }
  2019.  
  2020.         if(SendAbort)
  2021.         {
  2022.             CancelZModem();
  2023.             SendAbort = FALSE;
  2024.         }
  2025.  
  2026.         if(Config->CommandConfig->DownloadMacro[0])
  2027.             SerialCommand(Config->CommandConfig->DownloadMacro);
  2028.  
  2029.         Say(LocaleString(MSG_GLOBAL_TRANSFER_COMPLETED_TXT));
  2030.  
  2031.         DidTransfer = FALSE;
  2032.     }
  2033.     else
  2034.     {
  2035.         if(TransferFailed || TransferError)
  2036.         {
  2037.             if(Config->TransferConfig->TransferNotification == XFERNOTIFY_ALWAYS || Config->TransferConfig->TransferNotification == XFERNOTIFY_END)
  2038.                 WakeUp(TransferWindow,SOUND_BADTRANSFER);
  2039.  
  2040.             DeleteTransferPanel(TRUE);
  2041.         }
  2042.         else
  2043.         {
  2044.             if(TransferWindow)
  2045.             {
  2046.                 if(Config->TransferConfig->TransferNotification == XFERNOTIFY_ALWAYS || Config->TransferConfig->TransferNotification == XFERNOTIFY_END)
  2047.                     WakeUp(TransferWindow,SOUND_GOODTRANSFER);
  2048.  
  2049.                 DelayTime(2,0);
  2050.             }
  2051.  
  2052.             DeleteTransferPanel(FALSE);
  2053.         }
  2054.     }
  2055.  
  2056.     ReleaseWindows();
  2057. }
  2058.  
  2059.     /* RemoveUploadListItem(STRPTR Name):
  2060.      *
  2061.      *    Remove a named item from the upload list.
  2062.      */
  2063.  
  2064. VOID
  2065. RemoveUploadListItem(STRPTR Name)
  2066. {
  2067.     BPTR NameLock;
  2068.  
  2069.     if(NameLock = Lock(Name,ACCESS_READ))
  2070.     {
  2071.         struct GenericList *List;
  2072.         struct Node *Node;
  2073.         STRPTR Base;
  2074.         BOOL Done;
  2075.  
  2076.         List = GenericListTable[GLIST_UPLOAD];
  2077.         Base = FilePart(Name);
  2078.  
  2079.         LockGenericList(List);
  2080.  
  2081.         for(Node = (struct Node *)List->ListHeader.mlh_Head, Done = FALSE ; !Done && Node->ln_Succ ; Node = Node->ln_Succ)
  2082.         {
  2083.             if(!Stricmp(Base,FilePart(Node->ln_Name)))
  2084.             {
  2085.                 BPTR ListLock;
  2086.  
  2087.                 if(ListLock = Lock(Node->ln_Name,ACCESS_READ))
  2088.                 {
  2089.                     if(SameLock(ListLock,NameLock) == LOCK_SAME)
  2090.                     {
  2091.                         DeleteGenericListNode(List,Node,TRUE);
  2092.  
  2093.                         Done = TRUE;
  2094.                     }
  2095.  
  2096.                     UnLock(ListLock);
  2097.                 }
  2098.             }
  2099.         }
  2100.  
  2101.         UnlockGenericList(List);
  2102.  
  2103.         UnLock(NameLock);
  2104.     }
  2105. }
  2106.  
  2107.     /* CloseXPR():
  2108.      *
  2109.      *    Close the XPR library if it is still open.
  2110.      */
  2111.  
  2112. VOID
  2113. CloseXPR()
  2114. {
  2115.     if(XProtocolBase)
  2116.     {
  2117.         XProtocolCleanup(XprIO);
  2118.  
  2119.         CloseLibrary(XProtocolBase);
  2120.         XProtocolBase = NULL;
  2121.  
  2122.         SerWriteUpdate();
  2123.         ConTransferUpdate();
  2124.  
  2125.         SetTransferMenu(TRUE);
  2126.     }
  2127. }
  2128.  
  2129.     /* ChangeProtocol(STRPTR ProtocolName):
  2130.      *
  2131.      *    Select a different file transfer protocol.
  2132.      */
  2133.  
  2134. BOOL
  2135. ChangeProtocol(STRPTR ProtocolName,LONG Type)
  2136. {
  2137.     if(Type == XFER_DEFAULT)
  2138.     {
  2139.         ProtocolName = Config->TransferConfig->DefaultLibrary;
  2140.         Type = Config->TransferConfig->DefaultType;
  2141.     }
  2142.  
  2143.     if(Type == XFER_XPR)
  2144.     {
  2145.         if(ProtocolName && !ProtocolName[0])
  2146.             ProtocolName = NULL;
  2147.  
  2148.         if(!ProtocolName)
  2149.             ProtocolName = Config->TransferConfig->DefaultLibrary;
  2150.  
  2151.         if(!Stricmp(ProtocolName,LastXprLibrary) && XProtocolBase)
  2152.             return(TRUE);
  2153.     }
  2154.  
  2155.         /* Close the old library if still open. */
  2156.  
  2157.     CloseXPR();
  2158.  
  2159.     if(Type == XFER_INTERNAL)
  2160.     {
  2161.         UsesZModem = FALSE;
  2162.  
  2163.         strcpy(TransferProtocolName,"ASCII");
  2164.  
  2165.         SetTransferMenu(TRUE);
  2166.  
  2167.         return(TRUE);
  2168.     }
  2169.  
  2170.     if(Type == XFER_EXTERNALPROGRAM)
  2171.     {
  2172.         CommonExternalSetup(ProtocolName);
  2173.  
  2174.         return(TRUE);
  2175.     }
  2176.  
  2177.     return(CommonXPRSetup(ProtocolName,FALSE));
  2178. }
  2179.  
  2180.     /* ProtocolSetup(BOOL IgnoreOptions):
  2181.      *
  2182.      *    Set up the library and options for the external protocol.
  2183.      */
  2184.  
  2185. BOOL
  2186. ProtocolSetup(BOOL IgnoreOptions)
  2187. {
  2188.         /* Close the old library if still open. */
  2189.  
  2190.     CloseXPR();
  2191.  
  2192.     if(Config->TransferConfig->DefaultType == XFER_EXTERNALPROGRAM)
  2193.     {
  2194.         if(Config->TransferConfig->DefaultLibrary[0])
  2195.         {
  2196.             CommonExternalSetup(Config->TransferConfig->DefaultLibrary);
  2197.  
  2198.             return(TRUE);
  2199.         }
  2200.         else
  2201.             return(FALSE);
  2202.     }
  2203.  
  2204.     return(CommonXPRSetup(LastXprLibrary,IgnoreOptions));
  2205. }
  2206.